package Menu;

import com.mysql.jdbc.PreparedStatement;
import graphicswithsomebackup.GamePanel;
import graphicswithsomebackup.MouseLocator;

import com.mysql.jdbc.Statement;
import graphicswithsomebackup.BackGround;
import java.awt.Color;
import java.awt.Font;

import java.awt.Graphics;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JOptionPane;

/**
 *
 * @author Martin Wilhelmsson
 */

public class HighScoreHandler {

    // --------- Primitive types --------------
    private int panelWidth;
    private int panelHeight;

    private int nameDisplayX = 200;
    private int nameAndScoreDisplayY = 100;
    private int displaySpacing = 25;
    private int scoreDisplayX = nameDisplayX + 150;
    //.........................................

    // --------- Reference types --------------
    private BackGround bg;
    private GamePanel superPanel;
    private MouseLocator mousePositions = new MouseLocator();
    private Button returnButton;
    private Statement st;
    private boolean getArraysOnce = true;

    private ArrayList<String> theNames = new ArrayList<String>();
    private ArrayList<Integer> theScores = new ArrayList<Integer>();

    //access to the database
    String URL = "jdbc:mysql://194.47.47.18:3306/DA5221_GRP13?user=DA5221_GRP13&password=oFs11f";
    //.........................................


    public HighScoreHandler( GamePanel superPanel, int  panelWidth, int panelHeight ) {
        this.panelWidth = panelWidth;
        this.panelHeight = panelHeight;
        returnButton = new Button("back.png", true, 50, 500, 150, 87, superPanel, mousePositions);
        this.superPanel = superPanel;
        bg = new BackGround(panelWidth, panelHeight);
    }

    public HighScoreHandler() { }


    /**
     * Establishes a connection-object that the other methods can use.
     */
    private Connection connectionEstablisher() {
        try {
            Class.forName("com.mysql.jdbc.Driver").newInstance();
            Connection c = DriverManager.getConnection(URL);
            System.out.println("you are connected "+c.toString());
            return c;
        }
        catch (Exception e)
        {
            System.out.println(e);
            return null;
        }
    }

    /**
     * What do you think? Clears the table, but columns remain intact.
     */
    public void clearTable() {
        try {
            Connection c = connectionEstablisher();
            Statement st = (Statement) c.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
            st.executeUpdate("TRUNCATE TABLE highscores");
        } catch (SQLException ex) {
            Logger.getLogger(HighScoreHandler.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Decides if the new highscore is high enough to be entered as a new highscore.
     * When a player is finished playing, this method should be called!
     * @param key
     * @param name of the player
     * @param score
     */
    public void newHighScoreSetter(int score) {
        try {
            Connection c = connectionEstablisher();
            Statement st = (Statement) c.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
            ResultSet result = st.executeQuery("SELECT * FROM highscores"); //get context of database into a resultset

            int lowestValue = 0;
            int lowestValRow = 0;
            int numOfRows = 0;
            int keyVal = 1;

            //-------------------------------------------------------------------------------------
            /*
             * This piece of code checks out what the lowest value of the table is, and saves it along
             * with that specific rows rowValue. Used in next part of method below.
             * Also sets the key-value for the next row that will be inserted into the
             * player_ID-column. The way its done is not a good way of doing it but its a start.
             */
            if( result.first() ) { //if the table aint empty
                do {  //do-while ensures that this is gone through at least once. loops through the resultset.
                    numOfRows++;
                    if(lowestValue > result.getInt(3) ) {
                        lowestValue = result.getInt(3); //saves the currently lowest value
                        lowestValRow = result.getRow(); // and the row its on, so it maybe can be deleted later on
                        System.out.println("LowestValRow: "+lowestValRow);
                    }
                    //used for the new highscore. If I knew how to skip this I would.
                    if( keyVal <= result.getInt(1) ) {
                        keyVal = result.getInt(1) + 1; //one higher so they wont be the same.
                    }
                }
                while( result.next() == true ); //when it gets here, result points to the next row if any, or stops if there arent any more.
            }
            //-------------------------------------------------------------------------------------

            //_.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._
            //_.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._
            if( score > lowestValue ){
                /*
                 * If a new highscore is valid, we must check if it will fit.
                 * if there are already 10 values, an old value must be removed, the lowest value.
                 * Else, it just puts it tha databaze.
                 */

                String name = nameSetter();
                //Scanner inp = new Scanner(System.in);
                //System.out.println("You made a new highscore! Whats your name?? Enter it beloow!");
                //String name = inp.nextLine();
                if( numOfRows >= 10) { //if the lowest value in database is lower than the new score AND theres more than 10 rows in the database
                    System.out.println("more than 10 highscores");
                    result.absolute(lowestValRow);
                    result.deleteRow(); //delete the row with lowest value //When something is deleted by result.deleteRow, it seems to jump to the previuos row.
                    //first the resultSet has to move to the insert-row
                    result.moveToInsertRow();
                    result.updateInt(1, keyVal);
                    result.updateString(2, name);//do the insertion-commands
                    result.updateInt(3, score);
                    result.insertRow();//the insert it!
                }
                else if( numOfRows < 10) { // otherwise, just put the score in the highscore if theres less than 10 rows.
                    System.out.println("less than 10 highscores");
                    //first the resultSet has to move to the insert-row
                    result.moveToInsertRow();
                    result.updateInt(1, keyVal);
                    result.updateString(2, name);//do the insertion-commands
                    result.updateInt(3, score);//the insert it!
                    result.insertRow();
                }
            }

            else {
                System.out.println("Sorry pal, You didnt make it to the highscore!");
                //JOptionPane.showMessageDialog(superPanel, "Sorry mate, your score wasn't high enough!");
            }
            //_.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._
            //_.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._.-:^:-._

            result.close();
            st.close();
            c.close();
            System.out.println("End of newHighScoreSetter");

        } catch (SQLException ex) {
            Logger.getLogger(HighScoreHandler.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Should request the name from a player.
     * @return
     */
    public String nameSetter() {
        return JOptionPane.showInputDialog("Yooo made it to teh highscooore!!\nWhats your name daawwgghhh?");
    }

    /**
     * Used in da GamePanels paintComponent, so beware it loops forevvah mon'.
     * @param g
     * @param mouseLocator
     */
    public void drawHighScoreTable( Graphics g, MouseLocator mouseLocator) {
        bg.drawBackGround(g); //drawthebackground
        returnButton.drawButton(g, mouseLocator);
        displayHighScores(g);
        if(returnButton.isClicked) {
            superPanel.setShowHighScore(false); //highscore is off
            superPanel.setMenuIsOn(true); //menu is on
            this.getArraysOnce = true;
            returnButton.isClicked = false;
        }
        
    }

    /**
     * Is supposed to display the current highscores on screen!
     * @param g
     */
    private void displayHighScores(Graphics g) {
        g.setColor(Color.WHITE);
        g.setFont( new Font("serif", Font.BOLD, 20) );

        if(getArraysOnce) {
            fillArrays();
        }
        for(int i=0; i<theNames.size(); i++) { //needs only one arr since they both ar the same size!
            g.drawString( theNames.get(i) , nameDisplayX, (nameAndScoreDisplayY+displaySpacing*i) );
            g.drawString(Integer.toString(theScores.get(i)), scoreDisplayX, (nameAndScoreDisplayY+displaySpacing*i) );
        }
    }


    /**
     * when used, it should only be performed once!!!
     * the boolean "getNamesOnce" makes sure of this!
     * Fetches and array with all names.
     * @return
     */
    public void fillArrays() {
        try {
            theNames.clear();
            Connection c = connectionEstablisher();
            Statement st = (Statement) c.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
            ResultSet result = st.executeQuery("select player_name, score from da5221_grp13.highscores ORDER BY score DESC"); //get context of database into a resultset
            if( result.first() ) { //if the table aint empty
                do {  //do-while ensures that this is gone through at least once. loops through the resultset.
                    theNames.add(result.getString(1));
                    theScores.add(result.getInt(2));
                }
                while( result.next() == true ); //when it gets here, result points to the next row.
            }
            getArraysOnce = false;
            return;

        } catch (SQLException ex) {
            Logger.getLogger(HighScoreHandler.class.getName()).log(Level.SEVERE, null, ex);
        }
        getArraysOnce = false;
    }
//
    /**
     * old crap. Saving it just in case.
     */
    public static void performStuff() {
        String URL = "jdbc:mysql://194.47.47.18:3306/DA5221_GRP13?user=DA5221_GRP13&password=oFs11f";
        try {
            Class.forName("com.mysql.jdbc.Driver").newInstance();
            Connection c = DriverManager.getConnection(URL);

            System.out.println("you are connected "+c.toString());
            Statement st = (Statement) c.createStatement();
            //st.executeUpdate("UPDATE highscores SET player_id='5' WHERE player_name='smisk'");
            //st.executeUpdate("ALTER TABLE highscores DROP weight");  <----------- deleted the column called "weight"
            //st.execute("CREATE TABLE majsvelling(ID INTEGER not null)");-------skapad

        }
        catch (Exception e)
        {
            System.out.println(e);
        }
    }



}

/*public void createPrimaryKeyColumn() {
        try {
            Connection c = connectionEstablisher();
            Statement st = (Statement) c.createStatement();
            //st.executeUpdate("ALTER TABLE highscores ADD COLUMN player_ID VARCHAR(5)");
        } catch (SQLException ex) {
            Logger.getLogger(HighScoreHandler.class.getName()).log(Level.SEVERE, null, ex);
        }

    }*/